home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / a_utils / perl / mac-perl / gs_102st.bin / GUSI / GUSIFSp.cp / GUSIFSp.cp
Encoding:
Text File  |  1993-01-16  |  10.2 KB  |  558 lines  |  [TEXT/MPS ]

  1. /*********************************************************************
  2. Project    :    GUSI                -    Grand Unified Socket Interface
  3. File        :    GUSIFSp.cp        -    Dealing with paths
  4. Author    :    Matthias Neeracher <neeri@iis.ethz.ch>
  5. Started    :    15Jun92                                Language    :    MPW C++
  6.                 06Sep92    MN    Clear ioACUser
  7.                 12Sep92    MN    Renamed Paths.h to GUSIFSp_P.h
  8.                 15Nov92    MN    Forgot a few consts
  9.                 15Nov92    MN    Rename GUSIFSp_P.h to TFileSpec.h (there we go again)
  10.                 15Jan93    MN    IsParentOf
  11. Last        :    15Jan93
  12. *********************************************************************/
  13.  
  14. #include "GUSI_P.h"
  15. #include "TFileSpec.h"
  16.  
  17. #include <Errors.h>
  18. #include <Memory.h>
  19. #include <Aliases.h>
  20. #include <string.h>
  21. #include <ioctl.h>
  22. #include <fcntl.h>
  23. #include <errno.h>
  24.  
  25. OSErr TFileSpec::error;
  26. short TFileSpec::curVol;
  27. long    TFileSpec::curDir    =    -1;
  28.  
  29. OSErr TFileSpec::ChDir(const TFileSpec & spec)
  30. {
  31.     TFileSpec nudir(spec);
  32.     
  33.     nudir += "\p";
  34.     
  35.     if (error)
  36.         return error;
  37.     
  38.     curVol    =    nudir.vRefNum;
  39.     curDir    =    nudir.parID;
  40.  
  41.     return noErr;
  42. }
  43.  
  44. static OSErr CurrentDir(short & vRefNum, long & parID)
  45. {
  46.     OSErr        error;
  47.     WDPBRec    vol;
  48.     Str63        name;
  49.     
  50.     vol.ioNamePtr    =    name;
  51.     
  52.     if (error = PBHGetVolSync(&vol))
  53.         return error;
  54.         
  55.     vRefNum    =    vol.ioWDVRefNum;
  56.     parID        =    vol.ioWDDirID;
  57.     
  58.     return noErr;
  59. }
  60.  
  61. OSErr TFileSpec::Default()
  62. {
  63.     if (curDir != -1)    {
  64.         vRefNum    =    curVol;
  65.         parID        =    curDir;
  66.     } else if (error = CurrentDir(vRefNum, parID))
  67.         return error;
  68.     
  69.     --*this;
  70.     
  71.     return error;
  72. }
  73.  
  74. TFileSpec::TFileSpec(const FSSpec & spec, Boolean useAlias)                            
  75.     : FSSpec(spec) 
  76. {
  77.     if (!useAlias && hasAlias)
  78.         Resolve();
  79. }
  80.  
  81. TFileSpec::TFileSpec(short vRefNum, long parID, ConstStr31Param name, Boolean useAlias)
  82. {
  83.     this->vRefNum    =    vRefNum;
  84.     this->parID        =    parID;
  85.     memcpy(this->name, name, *name+1);
  86.         
  87.     if (!useAlias && hasAlias)
  88.         Resolve();    
  89. }
  90.  
  91. TFileSpec::TFileSpec(short wd, ConstStr31Param name, Boolean useAlias)
  92. {
  93.     WDPBRec     wdPB;
  94.     
  95.     wdPB.ioNamePtr     = nil;
  96.     wdPB.ioVRefNum     = wd;
  97.     wdPB.ioWDIndex     = 0;
  98.     wdPB.ioWDProcID     = 0;
  99.     
  100.     /* Change the Working Directory number in vRefnum into a real vRefnum */
  101.     /* and DirID. The real vRefnum is returned in ioVRefnum, and the real */
  102.     /* DirID is returned in ioWDDirID. */
  103.     
  104.     if (error = PBGetWDInfoSync(&wdPB))
  105.         return;
  106.     
  107.     vRefNum    = wdPB.ioWDVRefNum;
  108.     parID        = wdPB.ioWDDirID;
  109.     memcpy(this->name, name, *name+1);
  110.     
  111.     if (!useAlias && hasAlias)
  112.         Resolve();
  113. }
  114.  
  115. #define    maxPathLen 512
  116.  
  117. static char fullPath[maxPathLen];
  118.  
  119. /* Convert an FSSpec into a full pathname. The pathname is accumulated on the
  120.    high end of path to avoid excessive copying.
  121. */
  122.  
  123. char * TFileSpec::FullPath() const
  124. {
  125.     CInfoPBRec  block;
  126.     char *        curPath;
  127.     
  128.     /* Special case: a volume was specified */
  129.     if (parID == fsRtParID)    {
  130.         memcpy(fullPath, name+1, *name);
  131.         curPath        =    fullPath+*name;
  132.         curPath[0]    =    ':';
  133.         curPath[1]    =    0;
  134.         error            =    noErr;
  135.         
  136.         return fullPath;
  137.     }
  138.         
  139.     fullPath[maxPathLen-1]    =    0;
  140.     curPath                         =    fullPath+maxPathLen-*name-1;
  141.     
  142.     memcpy(curPath, name+1, *name);
  143.     
  144.    block.dirInfo.ioNamePtr = (StringPtr) fullPath;
  145.    block.dirInfo.ioDrParID = parID;
  146.  
  147.    do {
  148.       block.dirInfo.ioVRefNum     = vRefNum;
  149.       block.dirInfo.ioFDirIndex = -1;
  150.       block.dirInfo.ioDrDirID     = block.dirInfo.ioDrParID;
  151.  
  152.       if (error = PBGetCatInfoSync(&block))
  153.              return "";
  154.       *--curPath    =    ':';
  155.         curPath    -=    *fullPath;
  156.         memmove(curPath, fullPath+1, *fullPath);
  157.    } while (block.dirInfo.ioDrDirID != fsRtDirID);
  158.  
  159.     return curPath;
  160. }
  161.  
  162. char * TFileSpec::RelPath() const
  163. {
  164.     short            curVRef;
  165.     long            curDirID;
  166.     CInfoPBRec  block;
  167.     char *        curPath;
  168.             
  169.     if (error = CurrentDir(curVRef, curDirID))
  170.         return "";
  171.     
  172.     /* Special case: a volume was specified */
  173.     if (parID == fsRtParID)    {
  174.         if (vRefNum == curVRef && curDirID == fsRtDirID)
  175.             curPath = fullPath;
  176.         else {
  177.             memcpy(fullPath, name+1, *name);
  178.             curPath        =    fullPath+*name;
  179.         }
  180.         
  181.         curPath[0]    =    ':';
  182.         curPath[1]    =    0;
  183.         
  184.         return fullPath;
  185.     }
  186.  
  187.     block.dirInfo.ioNamePtr        =    (StringPtr)fullPath;
  188.     block.dirInfo.ioVRefNum     =     curVRef;
  189.     block.dirInfo.ioFDirIndex     =     -1;
  190.     block.dirInfo.ioDrDirID     =     curDirID;
  191.     
  192.     if (error = PBGetCatInfoSync(&block))
  193.         return "";
  194.     
  195.     if (curVRef == vRefNum 
  196.         && block.dirInfo.ioDrParID == parID
  197.         && !memcmp (fullPath, name, *fullPath+1)
  198.     )    {
  199.         fullPath[0]    =    ':';
  200.         fullPath[1] =     0;
  201.         
  202.         return fullPath;
  203.     }
  204.         
  205.     fullPath[maxPathLen-1]    =    0;
  206.     curPath                         =    fullPath+maxPathLen-*name-1;
  207.     
  208.     memcpy(curPath, name+1, *name);
  209.     
  210.    block.dirInfo.ioNamePtr = (StringPtr) fullPath;
  211.    block.dirInfo.ioDrParID = parID;
  212.  
  213.    do {
  214.       *--curPath    =    ':';
  215.          
  216.         /* Test fur current directory */
  217.         if (curVRef == vRefNum && curDirID == block.dirInfo.ioDrParID)
  218.             return strchr(curPath+1, ':') ? curPath : curPath+1;
  219.             
  220.         block.dirInfo.ioVRefNum     = vRefNum;
  221.         block.dirInfo.ioFDirIndex = -1;
  222.         block.dirInfo.ioDrDirID     = block.dirInfo.ioDrParID;
  223.         
  224.         if (error = PBGetCatInfoSync(&block))
  225.             return "";
  226.         curPath    -=    *fullPath;
  227.         memmove(curPath, fullPath+1, *fullPath);
  228.    } while (block.dirInfo.ioDrDirID != fsRtDirID);
  229.  
  230.     return curPath;
  231. }    
  232.  
  233. OSErr    TFileSpec::CatInfo(CInfoPBRec & info, Boolean dirInfo) const
  234. {
  235.    info.dirInfo.ioVRefNum         = vRefNum;
  236.    info.dirInfo.ioDrDirID         = parID;
  237.    info.dirInfo.ioNamePtr         = name;
  238.    info.dirInfo.ioFDirIndex     = dirInfo ? -1 : 0;
  239. #ifdef OnceThisFieldIsDefined
  240.     info.dirInfo.ioACUser         = 0;
  241. #else
  242.     info.dirInfo.filler2         = 0;
  243. #endif
  244.         
  245.    return error = PBGetCatInfoSync(&info);
  246. }
  247.  
  248. TFileSpec TFileSpec::operator--()
  249. {
  250.     CInfoPBRec  cb;
  251.     
  252.       CatInfo(cb, true);
  253.     
  254.     if (!error)
  255.         parID    = cb.dirInfo.ioDrParID;
  256.     
  257.     return *this;
  258. }
  259.  
  260. TFileSpec TFileSpec::operator-=(int levels)
  261. {
  262.     while (levels-- > 0)    {
  263.         --*this;
  264.         if (this->Error())
  265.             break;
  266.     }
  267.     
  268.     return *this;
  269. }
  270.  
  271. TFileSpec TFileSpec::operator-(int levels) const
  272. {
  273.     TFileSpec    spec    =    *this;
  274.     
  275.     return spec -= levels;
  276. }
  277.  
  278. inline OSErr TFileSpec::Resolve(const CInfoPBRec & info)
  279. {
  280.     Boolean        isFolder;
  281.     Boolean        wasAlias;
  282.     
  283.     return error = 
  284.         (hasAlias && IsAlias(info)) ? 
  285.             ResolveAliasFile(this, true, &isFolder, &wasAlias) :
  286.             noErr;
  287. }
  288.  
  289. OSErr TFileSpec::Resolve(Boolean gently)
  290. {
  291.     CInfoPBRec    ourinfo;
  292.     
  293.     CatInfo(ourinfo);
  294.     
  295.     if (error)
  296.         if (gently)
  297.             return error = noErr;
  298.         else
  299.             return error;
  300.     else
  301.         return Resolve(ourinfo);
  302. }
  303.  
  304. Boolean TFileSpec::Exists() const
  305. {
  306.     Boolean        res;
  307.     CInfoPBRec    ourinfo;
  308.     
  309.     res     = !CatInfo(ourinfo);
  310.     error    =    noErr;
  311.     
  312.     return res;
  313. }
  314.  
  315. Boolean TFileSpec::operator==(const TFileSpec & other) const
  316. {
  317.     return     vRefNum == other.vRefNum 
  318.         &&        parID == other.parID 
  319.         &&     EqualString(name, other.name, false, true);
  320. }
  321.  
  322. Boolean TFileSpec::operator!=(const TFileSpec & other) const
  323. {
  324.     return     vRefNum != other.vRefNum 
  325.         ||        parID != other.parID 
  326.         ||     !EqualString(name, other.name, false, true);
  327. }
  328.  
  329. Boolean TFileSpec::IsParentOf(const TFileSpec & other) const
  330. {
  331.     for (TFileSpec oth = other - 1; !oth.Error() && *this != oth; --oth);
  332.     
  333.     return !oth.Error();
  334. }
  335.  
  336. TFileSpec TFileSpec::operator+=(ConstStr31Param name)
  337. {
  338.     CInfoPBRec  cb;
  339.     
  340.    if (CatInfo(cb))
  341.         goto punt;
  342.     
  343.     // Resolve if an alias
  344.     
  345.     if (IsAlias(cb))
  346.         if (Resolve(cb) || CatInfo(cb))
  347.             goto punt;
  348.     
  349.     if (IsFile(cb)) {
  350.         error = bdNamErr;
  351.         
  352.         goto punt;
  353.     }
  354.     
  355.     parID    = cb.dirInfo.ioDrDirID;
  356.  
  357.     memcpy(this->name, name, *name+1);
  358.  
  359. punt:    
  360.     return *this;
  361. }
  362.  
  363. TFileSpec TFileSpec::operator+(ConstStr31Param name) const
  364. {
  365.     TFileSpec    spec    =    *this;
  366.     
  367.     return spec += name;
  368. }
  369.  
  370. TFileSpec TFileSpec::operator+=(const char * name)
  371. {
  372.     CInfoPBRec  cb;
  373.     
  374.    if (CatInfo(cb))
  375.         goto punt;
  376.     
  377.     // Resolve if an alias
  378.     
  379.     if (IsAlias(cb))
  380.         if (Resolve(cb) || CatInfo(cb))
  381.             goto punt;
  382.     
  383.     if (IsFile(cb)) {
  384.         error = bdNamErr;
  385.         
  386.         goto punt;
  387.     }
  388.         
  389.     if (IsFile(cb)) {
  390.         error = bdNamErr;
  391.         
  392.         goto punt;
  393.     }
  394.     
  395.     parID    = cb.dirInfo.ioDrDirID;
  396.  
  397.     memcpy(this->name+1, name, *this->name = strlen(name));
  398.  
  399. punt:    
  400.     return *this;
  401. }
  402.  
  403. TFileSpec TFileSpec::operator+(const char * name) const
  404. {
  405.     TFileSpec    spec    =    *this;
  406.     
  407.     return spec += name;
  408. }
  409.  
  410. TFileSpec TFileSpec::operator[](short index) const
  411. {
  412.     TFileSpec    spec     = *this;
  413.     CInfoPBRec  cb;
  414.     
  415.    cb.dirInfo.ioVRefNum     = spec.vRefNum;
  416.    cb.dirInfo.ioDrDirID         = spec.parID;
  417.    cb.dirInfo.ioNamePtr     = spec.name;
  418.    cb.dirInfo.ioFDirIndex     = index;
  419.  
  420.    error = PBGetCatInfoSync(&cb);
  421.     
  422.     return spec;
  423. }
  424.  
  425. TFileSpec::TFileSpec(const char * path, Boolean useAlias)
  426. {
  427.     int            pathLen    =     strlen(path);
  428.     StringPtr    name        =    (StringPtr) fullPath;
  429.     char *        nextPath;
  430.     
  431.     if (path[0] == ':' || !(nextPath = strchr(path, ':'))) {
  432.         Default();
  433.         
  434.         if (*path == ':')
  435.             ++path;
  436.     } else {
  437.         ParamBlockRec    vol;
  438.         
  439.         memcpy(name+1, (char *) path, *name = nextPath - (char *)  path + 1);
  440.         
  441.         vol.volumeParam.ioNamePtr    =    name;
  442.         vol.volumeParam.ioVolIndex    =    -1;
  443.         
  444.         if (error = PBGetVInfoSync(&vol))
  445.             return;
  446.         
  447.         vRefNum    =    vol.volumeParam.ioVRefNum;
  448.         parID        =    fsRtDirID;
  449.         
  450.         path = nextPath + 1;
  451.  
  452.         --*this;
  453.     }
  454.         
  455.     if (error)
  456.         return;
  457.     
  458.     while (*path) {
  459.         if (*path == ':')    {
  460.             --*this;
  461.             ++path;
  462.             
  463.             goto check;
  464.         }
  465.         
  466.         if (nextPath = strchr(path, ':'))
  467.             *nextPath = 0;
  468.         
  469.         *this += path;
  470.  
  471.         if (nextPath) {
  472.             *nextPath = ':';
  473.             path = nextPath + 1;
  474.         } else
  475.             break;
  476. check:            
  477.         if (error)
  478.             return;
  479.     }
  480.  
  481.     if (!useAlias && hasAlias)
  482.         Resolve();
  483. }
  484.  
  485. /* Convert a FSSpec into a full pathname. */
  486. char * FSp2FullPath(const FSSpec * desc)
  487. {
  488.     TFileSpec    spec(*desc);
  489.     
  490.     return spec.FullPath();
  491. }
  492.  
  493. /* Convert a FSSpec into a relative pathname. */
  494. char * FSp2RelPath(const FSSpec * desc)
  495. {
  496.     TFileSpec    spec(*desc);
  497.     
  498.     return spec.RelPath();
  499. }
  500.  
  501. /* Convert a working directory & file name into a FSSpec. */
  502. OSErr WD2FSSpec(short wd, ConstStr31Param name, FSSpec * desc)
  503. {
  504.     TFileSpec    spec(wd, name);
  505.     
  506.     *desc = spec;
  507.     
  508.     return spec.Error();
  509. }
  510.  
  511. /* Convert a pathname into a file spec. */
  512. OSErr Path2FSSpec(const char * path, FSSpec * desc)
  513. {
  514.     TFileSpec    spec(path);
  515.     
  516.     *desc = spec;
  517.     
  518.     return spec.Error();
  519. }
  520.  
  521. /* Return FSSpec of (vRefNum, parID) */
  522. OSErr FSpUp(FSSpec * desc)
  523. {
  524.     TFileSpec    spec(*desc);
  525.  
  526.     *desc = --spec;
  527.     
  528.     return spec.Error();
  529. }
  530.  
  531. /* Return FSSpec of file in directory denoted by desc */
  532. OSErr FSpDown(FSSpec * desc, ConstStr31Param name)
  533. {
  534.     TFileSpec    spec(*desc);
  535.  
  536.     *desc    = spec + name;
  537.     
  538.     return spec.Error();
  539. }
  540.  
  541. /* Call GetCatInfo for file system object. */
  542. OSErr    FSpCatInfo(const FSSpec * desc, CInfoPBRec * info)
  543. {
  544.     TFileSpec    spec(*desc);
  545.     
  546.     return spec.CatInfo(*info);
  547. }
  548.  
  549. /* Return FSSpec of nth file in directory denoted by (vRefNum, parID) */
  550. OSErr FSpIndex(FSSpec * desc, short n)
  551. {
  552.     TFileSpec    spec(*desc);
  553.     
  554.     *desc = spec[n];
  555.     
  556.     return spec.Error();
  557. }
  558.